/**
 * @标题: DateUtils.java
 * @包名： com.cares.mcp.util
 * @功能描述：
 * @作者： jason
 * @创建时间： 2014年9月25日 下午5:22:36
 * @version v0.0.1
 */

package com.example.lottery.util;

import lombok.extern.slf4j.Slf4j;

import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import java.text.DateFormat;
import java.text.DateFormatSymbols;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 日期工具类
 *
 * @author viphd
 * @version 1.0
 * @date 2019/07/11
 * <p>
 * 1. 日期格式化为字符串,format前缀
 * 2. 解析字符串日期为Date类型，parse前缀
 * 3. 计算时间差，calcDiff前缀
 */
@Slf4j
public class DateUtils {

    // region 日期时间格式
    /**
     * 获取当前年份
     */
    public static final String FORMAT_DATE_TIME_YEAR = "yy";


    /**
     * 日期格式：MM-dd-yy
     */
    public static final String FORMAT_DATE_TIME = "MM-dd-yy";

    /**
     * 默认日期时间格式：yyyy-MM-dd HH:mm:ss
     */
    public static final String FORMAT_DATE_TIME_DEFAULT = "yyyy-MM-dd HH:mm:ss";

    /**
     * 最小日期时间格式：yyyy-MM-dd HH:mm
     */
    public static final String FORMAT_DATE_TIME_MIN = "yyyy-MM-dd HH:mm";

    /**
     * 紧凑型日期时间格式，格式：yyyyMMddHHmmss
     */
    public static final String FORMAT_DATE_TIME_TIGHT = "yyyyMMddHHmmss";

    /**
     * ELK 规定日期时间格式：yyyy-MM-dd'T'HH:mm:ss.SSSXXX
     */
    public static final String FORMAT_DATE_TIME_ELK = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";

    /**
     * 日期精确到毫秒格式：yyyyMMddHHmmssSSS
     */
    public static final String FORMAT_DATE_TIME_MILL = "yyyyMMddHHmmssSSS";

    // endregion

    // region 日期格式

    /**
     * 默认日期格式：yyyy-MM-dd
     */
    public static final String FORMAT_DATE_DEFAULT = "yyyy-MM-dd";

    public static final String FORMAT_DATA_COMPACT = "yyyyMMdd";

    public static final String FORMAT_DATA_MONTH = "yyyyMM";

    // endregion

    // region 时间格式

    /**
     * 默认时间格式：HH:mm:ss
     */
    public static final String FORMAT_TIME_DEFAULT = "HH:mm:ss";

    // endregion

    // region 格式化日期

    /**
     * 格式化日期（格式：yy）
     */
    public static String formDate(Date date) {
        return formatDate(date, FORMAT_DATE_TIME_YEAR);
    }

    /**
     * 格式化日期（格式：yyyy-MM-dd）
     */
    public static String formatDate(Date date) {
        return formatDate(date, FORMAT_DATE_DEFAULT);
    }

    /**
     * 格式化日期（忽略时分秒）
     */
    public static Date ignoreHMS(Date date) {
        try {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat(FORMAT_DATE_DEFAULT);
            String s = simpleDateFormat.format(date);
            return simpleDateFormat.parse(s);
        } catch (ParseException e) {
            log.error("日期格式化异常", "", null, e);
        }
        return date;
    }

    /**
     * 格式化日期(缺省值0001-01-01)
     *
     * @param date   日期
     * @param format 需要转换的格式，建议使用DateUtils.FORMAT_xxx来获取格式
     * @return
     */
    public static String formatDate(Date date, String format) {
        return formatDate(date, format, "0001-01-01");
    }

    /**
     * 格式化日期
     *
     * @param date         日期
     * @param format       需要转换的格式，建议使用DateUtils.FORMAT_xxx来获取格式
     * @param defaultValue 默认值，如果date为空返回此值
     * @return
     */
    public static String formatDate(Date date, String format, String defaultValue) {
        String dateString;
        if (date == null) {
            dateString = defaultValue;
        } else {
            if (StringUtils.isEmpty(format)) {
                format = FORMAT_DATE_DEFAULT;
            }
            SimpleDateFormat formatter = new SimpleDateFormat(format);
            dateString = formatter.format(date);
        }
        return dateString;
    }

    public static Date formatSpecificDate(Date date, String format) {
        Date data;
        if (date == null) data = new Date();
        if (StringUtils.isNotEmpty(format)) format = FORMAT_DATE_DEFAULT;
        SimpleDateFormat formatter = new SimpleDateFormat(format);
        try {
            data = formatter.parse(formatter.format(date));
            return data;
        } catch (ParseException e) {
            log.error("日期格式化异常", "", null, e);
        }
        return null;
    }


    /**
     * 增减年数
     */
    public static Date addYears(Date origin, int amount) {
        return add(origin, Calendar.YEAR, amount);
    }

    /**
     * 增减月数
     */
    public static Date addMonths(Date origin, int amount) {
        return add(origin, Calendar.MONTH, amount);
    }

    /**
     * 增减天数
     */
    public static Date addDays(Date origin, int amount) {
        return add(origin, Calendar.DAY_OF_YEAR, amount);
    }

    /**
     * 增减小时数
     */
    public static Date addHours(Date origin, int amount) {
        return add(origin, Calendar.HOUR_OF_DAY, amount);
    }

    /**
     * 增减分钟数
     */
    public static Date addMinutes(Date origin, int amount) {
        return add(origin, Calendar.MINUTE, amount);
    }

    /**
     * 增减秒数
     */
    public static Date addSeconds(Date origin, int amount) {
        return add(origin, Calendar.SECOND, amount);
    }

    /**
     * 增减毫秒数
     */
    public static Date addMilliseconds(Date origin, int amount) {
        return add(origin, Calendar.MILLISECOND, amount);
    }

    private static Date add(Date origin, int field, int amount) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(origin);
        calendar.add(field, amount);
        return calendar.getTime();
    }

    // endregion

    /**
     * 获取当前日期时间
     *
     * @param format 日期时间格式
     * @return
     */
    public static String getCurrentDateTimeStr(String format) {
        Date currentTime = new Date();
        return formatDate(currentTime, format);
    }

    public static Date getCurrentDate() {
        Date currentDate = new Date();
        return currentDate;
    }

    public static String getCurrentDateStr() {
        Date currentTime = new Date();
        SimpleDateFormat formatter = new SimpleDateFormat(FORMAT_DATE_DEFAULT);
        return formatter.format(currentTime);
    }

    /**
     * 判断指定时间是否在日期范围内
     *
     * @param appDate   指定时间
     * @param startDate 范围开始时间
     * @param endDate   范围结束时间
     * @return
     */
    public static boolean WithinDateRange(Date appDate, Date startDate, Date endDate) {
        if (appDate.getTime() == startDate.getTime() || appDate.getTime() == endDate.getTime()) {
            return true;
        }
        Calendar date = Calendar.getInstance();
        date.setTime(appDate);
        Calendar begin = Calendar.getInstance();
        begin.setTime(startDate);
        Calendar end = Calendar.getInstance();
        end.setTime(endDate);
        if (date.after(begin) && date.before(end)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 获取当前月第一天
     *
     * @return str获取当前月第一天
     */
    public static String firstDayofMonth() {
        Calendar c = Calendar.getInstance();
        c.add(Calendar.MONTH, 0);
        c.set(Calendar.DAY_OF_MONTH, 1);//设置为1号,当前日期既为本月第一天
        String first = new SimpleDateFormat(FORMAT_DATE_DEFAULT).format(c.getTime());
        return first;
    }

    /**
     * 获取当前月最后一天
     *
     * @return str获取当前月最后一天
     */
    public static String lastDayofMonth() {
        Calendar ca = Calendar.getInstance();
        ca.set(Calendar.DAY_OF_MONTH, ca.getActualMaximum(Calendar.DAY_OF_MONTH));
        return new SimpleDateFormat(FORMAT_DATE_DEFAULT).format(ca.getTime());
    }

    /**
     * 获取上月第一天
     *
     * @return str获取当前月第一天
     */
    public static String firstDayofPreviousMonth() {
        Calendar c = Calendar.getInstance();
        c.add(Calendar.MONTH, -1);
        c.set(Calendar.DAY_OF_MONTH, 1);//设置为1号,当前日期既为本月第一天
        String first = new SimpleDateFormat(FORMAT_DATE_DEFAULT).format(c.getTime());
        return first;
    }

    /**
     * 获取上月最后一天
     *
     * @return str获取当前月最后一天
     */
    public static String lastDayofPreviousMonth() {
        Calendar ca = Calendar.getInstance();
        int month = ca.get(Calendar.MONTH);
        ca.set(Calendar.MONTH, month - 1);
        ca.set(Calendar.DAY_OF_MONTH, ca.getActualMaximum(Calendar.DAY_OF_MONTH));
        return new SimpleDateFormat(FORMAT_DATE_DEFAULT).format(ca.getTime());
    }

    /**
     * 获取指定日期所属月份的第一天
     */
    public static Date getFirstDayOfDateMonth(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(Calendar.MONTH, 0);
        c.set(Calendar.DAY_OF_MONTH, 1);
        return c.getTime();
    }

    /**
     * 获取指定日期所属月份的最后一天
     */
    public static Date getLastDayOfDateMonth(Date date) {
        Calendar ca = Calendar.getInstance();
        ca.setTime(date);
        ca.set(Calendar.DAY_OF_MONTH, ca.getActualMaximum(Calendar.DAY_OF_MONTH));
        return ca.getTime();
    }

    /**
     * 获取当前日期是一年中的第几天
     */
    public static String getDayOfYear(Date date) throws ParseException {
        String time = formatDate(date, FORMAT_DATE_DEFAULT);
        DateFormat fm = new SimpleDateFormat(FORMAT_DATE_DEFAULT);
        Date d = fm.parse(time);
        String str = String.format("%tj", d);//得到time日期是在这年的第几天
        return str;
    }

    /**
     * 获取当前年份的第一天
     */
    public static Date getCurrYearFirst() {
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        return getYearFirst(year);
    }

    /**
     * 获取当前年份的第一天
     */
    public static Date getCurrYearLast() {
        Calendar calendar = Calendar.getInstance();
        int year = calendar.get(Calendar.YEAR);
        return getYearLast(year);
    }

    /**
     * 获取指定年份的第一天
     */
    public static Date getYearFirst(int year) {
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        return calendar.getTime();
    }

    /**
     * 获取指定年份的最后一天
     */
    public static Date getYearLast(int year) {
        Calendar calendar = Calendar.getInstance();
        calendar.clear();
        calendar.set(Calendar.YEAR, year);
        calendar.roll(Calendar.DAY_OF_YEAR, -1);
        return calendar.getTime();
    }

    /**
     * 获取当前季度的结束日期
     *
     * @param date
     * @return
     */
    public static Date getSeasonEndDate(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int month = calendar.get(Calendar.MONTH);
        calendar.set(Calendar.MONTH, (month + 3) / 3 * 3);
        calendar.set(Calendar.DATE, 1);
        return new Date(calendar.getTime().getTime() - 24 * 60 * 60 * 1000);
    }

    /**
     * 获取当前季度的开始日期
     *
     * @param date
     * @return
     */
    public static Date getSeasonStartDate(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int month = calendar.get(Calendar.MONTH);
        calendar.set(Calendar.MONTH, month / 3 * 3);
        calendar.set(Calendar.DATE, 1);
        return calendar.getTime();
    }

    // region Old


    public static Date toDate(String dateString) {
        return toDate(dateString, FORMAT_DATE_DEFAULT);
    }

    public static Date toTranDate(Date date) {
        return toDate(formatDate(date, FORMAT_DATE_DEFAULT));
    }

    public static Date toTotalDate(String dateString) {
        return toDate(dateString, FORMAT_DATE_TIME_DEFAULT);
    }

    /**
     * 获取当前日期月份
     */
    public static String getCurrentMonthStr() {
        return getDateMonthStr(new Date());
    }

    /**
     * 获取日期月份
     */
    public static String getDateMonthStr(Date date) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMM");
        return formatter.format(date);
    }

    public static String getCurrentDateTimeStr() {
        Date currentTime = new Date();
        SimpleDateFormat formatter = new SimpleDateFormat(FORMAT_DATE_TIME_MIN);
        return formatter.format(currentTime);
    }

    public static String getDateString(Date date) {
        if (date == null) {
            return "";
        } else {
            return dateToString(date, FORMAT_DATE_DEFAULT);
        }
    }

    public static int convertIntDate(Date date) {
        return Integer.parseInt(new SimpleDateFormat(FORMAT_DATA_COMPACT).format(date));
    }


    public static String getDateStringAll(Date date) {
        SimpleDateFormat formatter = new SimpleDateFormat(FORMAT_DATE_TIME_MIN);
        return formatter.format(date);

    }

    public static String getDateStringAllDate(Date date) {
        SimpleDateFormat formatter = new SimpleDateFormat(FORMAT_DATE_TIME_DEFAULT);
        return formatter.format(date);

    }

    /**
     * Convert String to Date according to the format string
     *
     * @param dateString
     * @param format
     * @return
     */
    public static Date toDate(String dateString, String format) {
        try {
            SimpleDateFormat formatter = new SimpleDateFormat(format);
            return formatter.parse(dateString);
        } catch (Exception e) {
            //e.printStackTrace();
            return null;
        }
    }

    /**
     * 转换标准日期格式为英文格式　2010-08-01-->01AUG10
     *
     * @param dateStr
     * @return
     * @throws Exception
     */
    public static String getEnDateStrByCnDateStr(String dateStr) throws Exception {
        return new SimpleDateFormat("ddMMMyy", Locale.ENGLISH).format(new SimpleDateFormat(FORMAT_DATE_DEFAULT).parse(dateStr));
    }

    public static String getEnDateStrByCnDate(Date date) {
        return new SimpleDateFormat("ddMMMyy", Locale.ENGLISH).format(date);
    }


    public static List<String> getWeekDays(String dateStr) {
        List<String> dateList = new ArrayList<String>();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(toDate(dateStr));
        calendar.add(Calendar.DAY_OF_MONTH, -4);
        for (int i = 0; i <= 6; i++) {
            calendar.add(Calendar.DAY_OF_MONTH, 1);
            dateList.add(new SimpleDateFormat(FORMAT_DATE_DEFAULT).format(calendar.getTime()));
        }

        return dateList;
    }


    public static String getWeekStr(Date dt) {
        String[] weekDays = {"周日", "周一", "周二", "周三", "周四", "周五", "周六"};
        Calendar cal = Calendar.getInstance();
        cal.setTime(dt);
        int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (w < 0)
            w = 0;
        return weekDays[w];
    }

    //返回没有“周”前缀
    public static String getWeekStrNoZhou(Date dt) {
        String[] weekDays = {"日", "一", "二", "三", "四", "五", "六"};
        Calendar cal = Calendar.getInstance();
        cal.setTime(dt);
        int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
        if (w < 0)
            w = 0;
        return weekDays[w];
    }

    /**
     * 日期转化成字符串
     *
     * @param d      日期
     * @param format 格式
     * @return
     */
    public static String dateToString(Date d, String format) {
        if (d == null)
            return "";
        Hashtable<Object, Object> h = new Hashtable<>();
        StringBuilder javaFormat = new StringBuilder();
        String s = format.toLowerCase();
        if (s.contains("yyyy"))
            h.put(s.indexOf("yyyy"), "yyyy");
        else if (s.contains("yy"))
            h.put(s.indexOf("yy"), "yy");
        if (s.contains("mm"))
            h.put(s.indexOf("mm"), "MM");
        if (s.contains("dd"))
            h.put(s.indexOf("dd"), "dd");
        if (s.contains("hh24"))
            h.put(s.indexOf("hh24"), "HH");
        if (s.contains("mi"))
            h.put(s.indexOf("mi"), "mm");
        if (s.contains("ss"))
            h.put(s.indexOf("ss"), "ss");
        for (int intStart = 0; s.indexOf("-", intStart) != -1; intStart++) {
            intStart = s.indexOf("-", intStart);
            h.put(intStart, "-");
        }

        for (int intStart = 0; s.indexOf("/", intStart) != -1; intStart++) {
            intStart = s.indexOf("/", intStart);
            h.put(intStart, "/");
        }

        for (int intStart = 0; s.indexOf(" ", intStart) != -1; intStart++) {
            intStart = s.indexOf(" ", intStart);
            h.put(intStart, " ");
        }

        for (int intStart = 0; s.indexOf(":", intStart) != -1; intStart++) {
            intStart = s.indexOf(":", intStart);
            h.put(intStart, ":");
        }

        if (s.contains("\u5E74"))
            h.put(s.indexOf("\u5E74"), "\u5E74");
        if (s.contains("\u6708"))
            h.put(s.indexOf("\u6708"), "\u6708");
        if (s.contains("\u65E5"))
            h.put(s.indexOf("\u65E5"), "\u65E5");
        if (s.contains("\u65F6"))
            h.put(s.indexOf("\u65F6"), "\u65F6");
        if (s.contains("\u5206"))
            h.put(s.indexOf("\u5206"), "\u5206");
        if (s.contains("\u79D2"))
            h.put(s.indexOf("\u79D2"), "\u79D2");
        int i = 0;
        while (h.size() != 0) {
            Enumeration e = h.keys();
            Integer n = 0;
            while (e.hasMoreElements()) {
                i = (Integer) e.nextElement();
                if (i >= n)
                    n = i;
            }
            String temp = (String) h.get(n);
            h.remove(n);
            javaFormat.insert(0, temp);
        }
        SimpleDateFormat df = new SimpleDateFormat(javaFormat.toString(),
                new DateFormatSymbols());
        return df.format(d);
    }

    public static String convertDateToString(Date date, String format) {
        if (date != null) {
            try {
                SimpleDateFormat formatter = new SimpleDateFormat(format);
                return formatter.format(date);
            } catch (Exception e) {
                return "";
            }
        } else {
            return "";
        }
    }

    /**
     * yyyy年MM月dd日 HH时mm分ss秒
     *
     * @param date
     * @return
     */
    public static String convertToDateString(Date date) {
        return new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒").format(date);
    }


    public static Date genTKTLDate(Date date) {
        long longDate = date.getTime() + (1000 * 60 * 45);
        Date tktlDate = new Date();
        tktlDate.setTime(longDate);
        return tktlDate;
    }

    public static XMLGregorianCalendar convertToXMLGregorianCalendar(Date date) throws Exception {
        GregorianCalendar cal = new GregorianCalendar();
        cal.setTime(date);
        XMLGregorianCalendar gc = DatatypeFactory.newInstance().newXMLGregorianCalendar(cal);
        return gc;
    }

    public static XMLGregorianCalendar convertToXMLGregorianCalendar(String date, String format) throws Exception {
        GregorianCalendar cal = new GregorianCalendar();
        cal.setTime(convertStr2Date(date, format));
        XMLGregorianCalendar gc = DatatypeFactory.newInstance().newXMLGregorianCalendar(cal);
        return gc;
    }

    public static Date convertToDate(XMLGregorianCalendar cal) throws Exception {
        GregorianCalendar ca = cal.toGregorianCalendar();
        return ca.getTime();
    }

    public static Date convertStr2Date(String dateAsStr, String format) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.parse(dateAsStr);
    }

    public static String convertDate2Str(Date date, String format) throws Exception {
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(date);
    }

    /**
     * 增加或减少日期的天数
     * 增加为正数，减少为负数
     *
     * @param date
     * @param changeDays
     * @return
     */
    public static Date addOrLessDay(Date date, int changeDays) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        calendar.set(Calendar.DAY_OF_MONTH, calendar.get(Calendar.DAY_OF_MONTH) + changeDays);
        return calendar.getTime();
    }

    /**
     * 增加或减少日期的月数
     * 增加为正数，减少为负数
     *
     * @param date
     * @param changeMonth
     * @return
     */
    public static Date addOrLessMonth(Date date, int changeMonth) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) + changeMonth);
        return calendar.getTime();
    }


    /**
     * 增加或减少日期的秒数
     * 增加为正数，减少为负数
     *
     * @param date
     * @param second
     * @return
     */
    public static Date dateAddOrLessSecond(Date date, int second) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);

        calendar.add(Calendar.SECOND, second);
        return calendar.getTime();
    }

    /**
     * 两个时间差，单位天数
     *
     * @param startTime
     * @param endTime
     * @return
     */
    public static int dateDiff(String startTime, String endTime, String format) {
        SimpleDateFormat sd = new SimpleDateFormat(format);
        long diff;
        try {
            diff = sd.parse(endTime).getTime() - sd.parse(startTime).getTime();
        } catch (ParseException e) {
            return 0;
        }
        return (int) (diff / (1000 * 24 * 60 * 60) + 1);
    }

    /**
     * 两个时间差，单位天数（不包含当天）
     *
     * @param startTime
     * @param endTime
     * @return
     */
    public static int dateDiff(Date startTime, Date endTime) {
        try {
            long diff = startTime.getTime() - endTime.getTime();
            return (int) (diff / (1000 * 24 * 60 * 60));
        } catch (Exception e) {
            return 0;
        }
    }

    /**
     * 两个时间差，单位毫秒
     *
     * @param startDate
     * @param endDate
     * @return
     */
    public static long millisecondDiff(Date startDate, Date endDate) {
        return endDate.getTime() - startDate.getTime();
    }

    //供运价缓存用
    public static int dateDiffBySeconde(String endTime) {
        SimpleDateFormat sd = new SimpleDateFormat(FORMAT_DATE_DEFAULT);
        long diff;
        try {
            Date queryDate = addOrLessDay(sd.parse(endTime), 1);
            diff = queryDate.getTime() - new Date().getTime();
        } catch (ParseException e) {
            return 0;
        }
        return (int) (diff / 1000);
    }

    /**
     * 正则验证日期格式是否正确
     *
     * @param s
     * @param regex regex为null 默认为(20[0-3][0-9]-(0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|(20[0-3][0-9]-(0[2469]|11)-(0[1-9]|[12][0-9]|30))
     * @return
     */
    public static boolean checkDateStr(String s, String regex) {
        if (regex == null) {
            regex = "(20[0-3][0-9]-(0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|(20[0-3][0-9]-(0[2469]|11)-(0[1-9]|[12][0-9]|30))";
        }
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(s);
        return matcher.find();
    }

    //type 10检查开始 20检查结束
    public static String checkTime(String freTimeStr, String endTimeStr) {
        Date newDate = new Date();
        long nowDate = newDate.getTime();
        Date freDate = DateUtils.toTotalDate(freTimeStr);
        assert freDate != null;
        Date endDate = DateUtils.toTotalDate(endTimeStr);
        assert endDate != null;
        long freTime = freDate.getTime();
        long endTime = endDate.getTime();

        if (nowDate > endTime) {
            return "over";
        } else if (nowDate < freTime) {
            return "wait";
        } else {
            return "start";
        }
    }

    //判断当前日期在某个范围
    public static boolean CompareCurrenDate(String startDateStr, String endTimeStr) {
        Date date = new Date();//当前日期
        DateFormat df = new SimpleDateFormat(FORMAT_DATE_TIME_DEFAULT);
        try {
            Date startDate = df.parse(startDateStr);
            Date endDate = df.parse(endTimeStr);
            if (date.getTime() >= startDate.getTime() && date.getTime() <= endDate.getTime()) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 比较日期
     *
     * @param startDate
     * @param endTime
     * @return
     */
    public static boolean compareDate(Date startDate, Date endTime) {
        try {
            if (startDate.getTime() <= endTime.getTime()) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 比较日期是否相等
     */
    public static boolean isEquals(Date startDate, Date endDate) {
        try {
            if (startDate.getTime() == endDate.getTime()) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 比较大小
     */
    public static boolean compareSize(Date startDate, Date endDate) {
        try {
            if (startDate.getTime() < endDate.getTime()) {
                return true;
            } else {
                return false;
            }
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 比较两个日期的先后顺序
     *
     * @param first  第一个日期 @see Date
     * @param second 第二个日期 @see Date
     * @return 如果first==second，返回0; 如果first<second，返回-1; 如果first>second，返回1
     */
    public static int compareDate2(Date first, Date second) {
        if ((first == null) && (second == null)) {
            return 0;
        }

        if (first == null) {
            return -1;
        }

        if (second == null) {
            return 1;
        }

        if (first.before(second)) {
            return -1;
        }

        if (first.after(second)) {
            return 1;
        }
        return 0;
    }

    //返回周岁
    public static int getAgeByBirth(String birthDateStr, String curDateStr, String format) {
        int age = 0;
        try {
            Date curDate = toDate(curDateStr, format);
            Calendar now = Calendar.getInstance();
            assert curDate != null;
            now.setTime(curDate);// 当前时间
            Date birthDate = toDate(birthDateStr, format);
            Calendar birth = Calendar.getInstance();
            assert birthDate != null;
            birth.setTime(birthDate);
            if (birth.after(now)) {
                age = -1;  //表示不存在的出生日期
            } else {
                age = now.get(Calendar.YEAR) - birth.get(Calendar.YEAR);
                if (age == 0) {//表示同一年
                    age = 0;
                } else if (age > 0) {//表示跨年
                    if (now.get(Calendar.DAY_OF_YEAR) <= birth.get(Calendar.DAY_OF_YEAR)) { //不满一周年
                        age -= 1;
                    }
                }
            }
        } catch (Exception e) {
            age = -2;//表示出错
        }
        return age;
    }

    //返回时间戳  默认本地服务器时间
    public static long getTime() {
        return new Date().getTime();
    }

    //时间戳转为Date
    public static String timeStampToDateStr(long seconds) {
        try {
            Date date = new Date(seconds);
            return new SimpleDateFormat(FORMAT_DATE_DEFAULT).format(date);
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * 计算两个时区的时间差
     *
     * @param depTime 起飞当地区时
     * @param depZone 起飞当地时区
     * @param arrTime 到达当地区时
     * @param arrZone 到达当地时区
     * @return
     */
    public static long calDuration(String depTime, String depZone, String arrTime, String arrZone) {
        try {
            if (StringUtils.isEmpty(depZone)) {
                depZone = "8";
            }
            if (StringUtils.isNotEmpty(arrZone)) {
                arrZone = "8";
            }
            Date depDate = DateUtils.toDate(depTime, FORMAT_DATE_TIME_MIN);
            Date arrDate = DateUtils.toDate(arrTime, FORMAT_DATE_TIME_MIN);
            long diff;
            if (!depZone.equals(arrZone)) {//不同时区
                //计算到达时间相对出发时区的区时
                //计算区时  计算的区时=已知区时-（已知区时的时区-要计算区时的时区）
                Double depZoneInt = Double.parseDouble(depZone);//出发时区
                Double arrZoneInt = Double.parseDouble(arrZone);//到达时区
                int diffZone = (int) (arrZoneInt - depZoneInt);//到达地区与出发地区的时区差
                Date arrDateDepZone = DateUtils.dateAddOrLessSecond(arrDate, -(diffZone * 3600));//转换为出发地区时区的区时
                assert depDate != null;
                diff = DateUtils.millisecondDiff(depDate, arrDateDepZone);
            } else {
                assert arrDate != null;
                diff = DateUtils.millisecondDiff(depDate, arrDate);
            }
            return diff;
        } catch (Exception e) {
            return 0;
        }
    }

    /**
     * 将已知时区的区时转换为指定时区的区时
     *
     * @param dateTime
     * @param dateTimeZone
     * @param targetTimeZone 要计算区时的时区
     * @return
     */
    public static Date toTargetDate(String dateTime, String dateTimeZone, String targetTimeZone) {
        try {
            //计算区时  计算的区时=已知区时-（已知区时的时区-要计算区时的时区）
            Double dateTimeZoneInt = Double.parseDouble(dateTimeZone);//已知区时的时区
            Double targetTimeZoneInt = Double.parseDouble(targetTimeZone);//要计算区时的时区
            Date date = DateUtils.toDate(dateTime, FORMAT_DATE_TIME_MIN);
            int diffZone = (int) (dateTimeZoneInt - targetTimeZoneInt);//到达地区与出发地区的时区差
            return DateUtils.dateAddOrLessSecond(date, -(diffZone * 3600));
        } catch (Exception e) {
            return new Date();
        }
    }

    /**
     * 计算两个日期的跨天数   该方法比较有问题
     *
     * @return
     */
    public static int diffDays(String depTime, String depZone, String arrTime, String arrZone) {
        try {
            if (StringUtils.isEmpty(depZone)) {
                depZone = "8";
            }
            if (StringUtils.isNotEmpty(arrZone)) {
                arrZone = "8";
            }
            Date depDate = DateUtils.toDate(depTime, FORMAT_DATE_DEFAULT);
            //当地到达时间
            Date arrDate = DateUtils.toDate(arrTime, FORMAT_DATE_DEFAULT);
            int diff;
            if (!depZone.equals(arrZone)) {
                //计算出发时间相对到达时区的区时
                //计算区时  计算的区时=已知区时-（已知区时的时区-要计算区时的时区）
                //出发时区
                Double depZoneInt = Double.parseDouble(depZone);
                //到达时区
                Double arrZoneInt = Double.parseDouble(arrZone);
                //到达地区与出发地区的时区差
                int diffZone = (int) (depZoneInt - arrZoneInt);
                //转换为到达时区的出发时间
                Date depDateArrZone = DateUtils.dateAddOrLessSecond(depDate, -(diffZone * 3600));
                //天数
                diff = DateUtils.dateDiff(arrDate, depDateArrZone);
            } else {
                //天数
                diff = DateUtils.dateDiff(arrDate, depDate);
            }
            return diff;
        } catch (Exception e) {
            return 0;
        }
    }

    /**
     * 计算跨天数
     *
     * @return
     */
    public static int diffDaysWithHour(String depTime, String depZone, String arrTime, String arrZone) {
        try {
            if (StringUtils.isEmpty(depZone)) {
                depZone = "8";
            }
            if (StringUtils.isNotEmpty(arrZone)) {
                arrZone = "8";
            }
            Date depDate = DateUtils.toDate(depTime, FORMAT_DATE_TIME_MIN);
            //当地到达时间
            Date arrDate = DateUtils.toDate(arrTime, FORMAT_DATE_TIME_MIN);
            int diff;
            if (!depZone.equals(arrZone)) {
                //计算出发时间相对到达时区的区时
                //计算区时  计算的区时=已知区时-（已知区时的时区-要计算区时的时区）
                //出发时区
                Double depZoneInt = Double.parseDouble(depZone);
                //到达时区
                Double arrZoneInt = Double.parseDouble(arrZone);
                //到达地区与出发地区的时区差
                int diffZone = (int) (depZoneInt - arrZoneInt);
                //转换为到达时区的出发时间
                Date depDateArrZone = DateUtils.dateAddOrLessSecond(depDate, -(diffZone * 3600));
                //取出当地的日期yyyy-MM-dd
                String depDateArrZoneStr = convertDateToString(depDateArrZone, FORMAT_DATE_DEFAULT);
                String arrDateArrZoneStr = convertDateToString(arrDate, FORMAT_DATE_DEFAULT);
                //天数
                diff = diffDays(depDateArrZoneStr, arrZone, arrDateArrZoneStr, arrZone);
            } else {
                //取出当地的日期yyyy-MM-dd
                String depDateStr = convertDateToString(depDate, FORMAT_DATE_DEFAULT);
                String arrDateStr = convertDateToString(arrDate, FORMAT_DATE_DEFAULT);
                diff = diffDays(depDateStr, arrZone, arrDateStr, arrZone);
            }
            return diff;

        } catch (Exception e) {
            return 0;
        }
    }

    /**
     * 跨时区比较，统一转换为
     *
     * @param *             @param knownDateTim 已知区时
     * @param knownDateTime 已知时区
     * @param filter        过滤时间 1小时表示为1000
     * @return
     */
    public static boolean filterDateTimeWithZone(String localDateStr, String localZone, String knownDateTime, String knownTimeZone, long filter) {
        Date localDate = DateUtils.toDate(localDateStr, FORMAT_DATE_TIME_MIN);
        Date knownDateLocal;
        if (localZone.equals(knownDateTime)) {//同一时区的可不需要转换，直接使用
            knownDateLocal = DateUtils.toDate(knownDateTime, FORMAT_DATE_TIME_MIN);
        } else {
            knownDateLocal = toTargetDate(knownDateTime, knownTimeZone, localZone);
        }
        assert knownDateLocal != null;
        assert localDate != null;
        long dateLong = (knownDateLocal.getTime() - localDate.getTime()) / 3600 - filter;
        return dateLong > 0;
    }

    public static String timeStampToDateStr(long seconds, String format) {
        try {
            Date date = new Date(seconds);
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
            return simpleDateFormat.format(date);
        } catch (Exception e) {
            return "";
        }
    }

    /**
     * 当前日期减十二个月
     *
     * @param date
     * @return
     */
    public static String reduced(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MONTH, -12);
        Date time = cal.getTime();
        return DateUtils.formatDate(time, DateUtils.FORMAT_DATE_DEFAULT);
    }


    public static Date dateAddNumberOfDays(Date date) {
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.add(calendar.DATE, 180); //把日期往后增加一天,整数  往后推,负数往前移动
        Date specificDate = DateUtils.formatSpecificDate(calendar.getTime(), DateUtils.FORMAT_DATE_TIME);//这个时间就是日期往后推一天的结果
        return specificDate;
    }


    public static Date dateAddOne(Date date) {
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.add(calendar.DATE, 1); //把日期往后增加一天,整数  往后推,负数往前移动
        Date specificDate = DateUtils.formatSpecificDate(calendar.getTime(), DateUtils.FORMAT_DATE_TIME);//这个时间就是日期往后推一天的结果
        return specificDate;
    }

    public static Date dateSubtraction(Date date) {
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.add(calendar.DATE, -1); //把日期往后增加一天,整数  往后推,负数往前移动
        Date specificDate = DateUtils.formatSpecificDate(calendar.getTime(), DateUtils.FORMAT_DATE_TIME);//这个时间就是日期往后推一天的结果
        return specificDate;
    }


    public static Date dateAddMonth(Date date) {
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.add(calendar.MONTH, 1); //把日期往后增加一个月,整数  往后推,负数往前移动
        Date specificDate = DateUtils.formatSpecificDate(calendar.getTime(), DateUtils.FORMAT_DATE_TIME);//这个时间就是日期往后推一天的结果
        return specificDate;
    }


    /**
     * 表时间交集
     *
     * @param leftStartDate
     * @param leftEndDate
     * @param rightStartDate
     * @param rightEndDate
     * @return
     */
    public static boolean hasOverlap(Date leftStartDate, Date leftEndDate, Date rightStartDate, Date rightEndDate) {
        return ((leftStartDate.getTime() >= rightStartDate.getTime())
                && leftStartDate.getTime() <= rightEndDate.getTime())
                ||
                ((rightStartDate.getTime() >= leftStartDate.getTime())
                        && rightStartDate.getTime() <= leftEndDate.getTime());
    }

    /**
     * 两时间相减
     *
     * @param startDate
     * @param endDate
     * @return
     */
    public static long subtraction(Date startDate, Date endDate) {
        long startDateTime = startDate.getTime();
        long endDateTime = endDate.getTime();
        long secondTime = endDateTime - startDateTime;
        TimeUnit time = TimeUnit.DAYS;
        return time.convert(secondTime, TimeUnit.MILLISECONDS);
    }


    /**
     * 满足时间内
     *
     * @param expireDate
     * @return
     */
    public static boolean satisfyTimeInside(Date expireDate, String startDate, String endDate) {
        Date date = DateUtils.toDate(startDate, DateUtils.FORMAT_DATA_COMPACT);
        Date date1 = DateUtils.toDate(endDate, DateUtils.FORMAT_DATA_COMPACT);
        Date date2 = DateUtils.formatSpecificDate(expireDate, DateUtils.FORMAT_DATA_COMPACT);
        if (Objects.nonNull(date) && Objects.nonNull(date1) && Objects.nonNull(date2)) {
            long startTime = date.getTime();
            long endTime = date1.getTime();
            long expireTime = date2.getTime();
            if (startTime <= expireTime && expireTime <= endTime) {
                return true;
            }
        }
        return false;
    }


    public static int getAge(Date birth) {
        Calendar cal = Calendar.getInstance();
        int thisYear = cal.get(Calendar.YEAR);
        int thisMonth = cal.get(Calendar.MONTH);
        int dayOfMonth = cal.get(Calendar.DAY_OF_MONTH);
        cal.setTime(birth);
        int birthYear = cal.get(Calendar.YEAR);
        int birthMonth = cal.get(Calendar.MONTH);
        int birthdayOfMonth = cal.get(Calendar.DAY_OF_MONTH);
        int age = thisYear - birthYear;
        // 未足月
        if (thisMonth <= birthMonth) {
            // 当月
            if (thisMonth == birthMonth) {
                // 未足日
                if (dayOfMonth < birthdayOfMonth) {
                    age--;
                }
            } else {
                age--;
            }
        }
        return age;
    }

    /**
     * @description: 获取两个日期中所有的日期
     * @author bin sun
     * @date 2023/6/21 11:51
     */
    public static List<Date> getDatesBetween(Date startDate, Date endDate) {
        List<Date> dates = new ArrayList<>();
        LocalDate start = convertToLocalDate(startDate);
        LocalDate end = convertToLocalDate(endDate);
        long numOfDaysBetween = ChronoUnit.DAYS.between(start, end);
        for (int i = 0; i <= numOfDaysBetween; i++) {
            LocalDate date = start.plusDays(i);
            dates.add(convertToDate(date));
        }
        return dates;
    }

    public static LocalDate convertToLocalDate(Date date) {
        Instant instant = date.toInstant();
        ZoneId zone = ZoneId.systemDefault();
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
        return localDateTime.toLocalDate();
    }

    public static Date convertToDate(LocalDate date) {
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = date.atStartOfDay().atZone(zone).toInstant();
        return Date.from(instant);
    }
}
